﻿Imports System.Net.Sockets
Imports System.Threading
Imports System.Windows.Forms
Imports System.Net
Imports System.Text
Imports System.Runtime.InteropServices
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Runtime.CompilerServices
Public Class Form1

    '这是搞黑白棋的
    Private Enum Chess
        none = 0
        Black
        White
    End Enum
    Private Box As Chess(,) = New Chess(14, 14) {}
    Private mplayer As Chess = Chess.White   '以白棋先
    '通信，就是监听，跟课上讲的差不多
    Private ReadFlag As Boolean = True
    Private th As Thread '定义线程
    '定义远程结点，用来获取对方IP地址和发送信息
    Private remote As IPEndPoint
    Private udpclient As UdpClient  '它这用的是UDP，可能为了方便
    Private can_go As Boolean = False '能否走棋
    Private winner As Chess
    Private th_flag As Boolean = False
    Private Reset_flag As Boolean = False
    Private g As System.Drawing.Graphics
    Dim s As Socket = Nothing
    Dim t As Thread
    Dim MyIP As String
    ' Public Sub WaitData()
    'Dim temp As String
    '   s = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) '''使用TCP协议
    'Dim localEndPoint As New IPEndPoint(IPAddress.Parse(MyIP), 1025)  '''指定IP和Port
    '  s.Bind(localEndPoint)
    ' s.Listen(1000)     '''侦听，最多接受100个连接
    '  While (True)
    'Dim bytes(2048) As Byte   '''用来存储接收到的字节
    'm ss As Socket = s.Accept()  '''若接收到,则创建一个新的Socket与之连接
    '      ss.Receive(bytes)    '''接收数据，若用ss.send(Byte()),则发送数据
    'nd While
    ' End Sub

    Private Sub read()
        udpclient = New UdpClient(Convert.ToInt32(txt_port.Text))  '这里直接用toint32控制了长度
        remote = Nothing
        Dim enc As Encoding = Encoding.Unicode  '设定了编码类型
        Dim x As Integer, y As Integer  '连续定义x，y
        While ReadFlag = True
            Dim data As Byte() = udpclient.Receive(remote)
            '得到对方发送来的信息
            Dim strData As String = enc.GetString(data)
            Dim a As String() = New String(4) {}
            a = strData.Split("|"c)  '拆分字符串，可能在后面有用
            Thread.Sleep(2000)
            Select Case a(0)
                Case "join"
                    '获取传送信息到本地端口号的远程计算机IP地址
                    Dim remoteIP As String = remote.Address.ToString()
                    '显示接收信息以及传送信息的计算机IP地址
                    'Label6.Text = "已经加入你是黑方请走先棋"
                    mplayer = Chess.Black
                    ShowRole() '图片显示自己的角色（黑方，白方）
                    can_go = True '能走棋
                    BtnBuildGame.Enabled = False
                    Exit Select
                Case "move"
                    If Integer.TryParse(a(1), x) Then
                        x = Convert.ToInt16(a(1))
                        y = Convert.ToInt16(a(2))
                    Else
                        MessageBox.Show("可能是数组为空") ' 处理数组长度不足的情况
                    End If



                    '画对方棋子
                    Dim p As New Point(x, y)
                    '          Label1.Text = p.X.ToString() & "|" & p.Y.ToString()
                    Dim p2 As New Point(p.X * 35 + 4, p.Y * 35 + 4)
                    If Box(p.X, p.Y) <> Chess.none Then
                        Return
                    End If
                    ' Label2.Text = Box(p.X, p.Y).ToString()
                    can_go = True
                    ShowRole() '图片显示自己的角色（黑方，白方）
                    ' PictureBox1 = New PictureBox()
                    'Refresh()
                    PictureBox1.Invoke(Sub() PictureBox1 = New PictureBox())
                    Exit Select
                Case "over"
                    ' Label6.Text = a(1) & "赢了此局"
                    If a(1) = "Black" Then
                        winner = Chess.Black
                    Else
                        winner = Chess.White
                    End If
                    can_go = False
                    BtnReStart.Enabled = True
                    Exit Select
                Case "reset"
                    Reset_flag = True
                    If BtnReStart.Enabled = False Then
                        reset()
                        Reset_flag = False
                    End If
                    Exit Select
                Case "exit"
                    MessageBox.Show("对方推出了，游戏结束！", "提示")
                    Label6.Text = "对方推出了游戏结束！"
                    Exit While
            End Select
        End While
    End Sub
    Private Sub send(ByVal info As String)
        '创建udp网络服务
        Dim SendUdp As New UdpClient()
        Dim remoteIP As IPAddress
        Try  '判断IP地址的真确性
            remoteIP = IPAddress.Parse(txt_IP.Text)  '这直接用这个转换说实在的可能是为了装逼吧
        Catch
            MessageBox.Show("请输入正确的IP地址！", "错误")
            Return
        End Try
        Dim remoteep As New IPEndPoint(remoteIP, Convert.ToInt32(txt_remoteport.Text))
        Dim buffer As [Byte]() = Nothing
        Dim enc As Encoding = Encoding.Unicode
        Dim str As String = info
        buffer = enc.GetBytes(str.ToCharArray())
        '传送信息到指定计算机的 txt_remoteport端口号
        SendUdp.Send(buffer, buffer.Length, remoteep)
        SendUdp.Close()  '关闭udp网络服务
    End Sub
    Private Sub ShowRole()  '图片显示自己角色（黑方，白方）
        If mplayer = Chess.Black Then
            PictureBox2.Image = ImageList1.Images(0) '黑方
        Else
            PictureBox2.Image = ImageList1.Images(1) '白方
        End If
    End Sub

    Private Sub BtnBuildGame_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles BtnBuildGame.Click  '联机（好长）
        send("join|") '创建一个线程
        If th Is Nothing OrElse Not th.IsAlive Then
            th = New Thread(AddressOf read)

        End If

        ' th = New Thread(New ThreadStart(AddressOf read))
        th_flag = True
        th.Start()  '启动线程
        Label6.Text = "程序处于等待联机状态！"
        BtnBuildGame.Enabled = False
        '使用GetGraphicsObject 函数获取将用于绘图的图形对象的引用
        g = GetGraphicsObject(PictureBox1)

    End Sub
    Private Sub ThreadProc()
        ' 假设的一些长时间运行的任务
        Thread.Sleep(2000)
        BtnBuildGame.Invoke(Sub() BtnBuildGame.Text = "完成")
    End Sub


    Private Sub BtnReStart_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles BtnReStart.Click  '重新开始
        Cls_Box()
        reset()
        send("reset|")
        BtnReStart.Enabled = False
        Reset_flag = False
        '使用ggo函数获取将用于绘图的图形对象的引用
        g = GetGraphicsObject(PictureBox1)
    End Sub
    Private Sub Cls_Box()  '将存储棋子状态数组Box初始化
        PictureBox1.Refresh()
        For i As Integer = 0 To 14
            For j As Integer = 0 To 14
                Box(i, j) = Chess.none
            Next
        Next
    End Sub
    Private Sub reset()
        If mplayer = Chess.Black Then
            If Reset_flag = True Then
                '对方已经重新开始
                Label6.Text = "你是白方，处于重新开始状态！"
                mplayer = Chess.White
                can_go = False
            Else
                Label6.Text = "你是白方，处于等待对方重新开始状态！"
            End If
        Else
            If Reset_flag = True Then
                '对方已经重新开始
                Label6.Text = "你是黑方，请走先棋"
                mplayer = Chess.Black
                can_go = True
            Else
                Label6.Text = "你是黑方，处于等待对方重新开始状态！"
            End If
        End If
        ShowRole()  'xianshijueshe
    End Sub
    Private Function win_lose() As Boolean '扫描整个棋盘，判断是否五颗连线
        Dim a As Chess = mplayer
        Dim i As Integer, j As Integer
        For i = 0 To 10  '判断x=y轴上是否形成五连
            For j = 0 To 10
                If Box(i, j) = a AndAlso Box(i + 1, j + 1) = a AndAlso Box(i + 2, j + 2) = a AndAlso Box(i + 3, j + 3) = a AndAlso Box(i + 4, j + 4) = a Then
                    Return True
                End If
            Next
        Next
        For i = 4 To 14 'x=-y轴上是否有五连
            For j = 0 To 10
                If Box(i, j) = a AndAlso Box(i - 1, j + 1) = a AndAlso Box(i - 2, j + 2) = a AndAlso Box(i - 3, j + 3) = a AndAlso Box(i - 4, j + 4) = a Then
                    Return True
                End If
            Next
        Next
        For i = 0 To 14 'y轴上成立
            For j = 4 To 14
                If Box(i, j) = a AndAlso Box(i, j - 1) = a AndAlso Box(i, j - 2) = a AndAlso Box(i, j - 3) = a AndAlso Box(i, j - 4) = a Then
                    Return True
                End If
            Next
        Next
        For i = 0 To 10 'x成立
            For j = 0 To 14
                If Box(i, j) = a AndAlso Box(i + 1, j) = a AndAlso Box(i + 2, j) = a AndAlso Box(i + 3, j) = a AndAlso Box(i + 4, j) = a Then
                    Return True
                End If
            Next
        Next
        Return False
    End Function
    Private Sub PictureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseDown
        If can_go <> True Then
            MessageBox.Show("不能走棋，请等待对方")
            Return
        End If
        '（e.x,e.y）是鼠标点击位置
        Dim p As New Point((e.X - 4) \ 35, (e.Y - 4) \ 35) '换算成棋盘坐标
        If p.X < 0 OrElse p.Y < 0 OrElse p.X > 15 OrElse p.Y > 15 Then
            MessageBox.Show("超越边界了")
            Return
        End If
        Dim ch As Char = Chr(p.Y + 65)
        'Label1.Text = p.X.ToString() & "|" & p.Y.ToString()
        Dim p2 As New Point(p.X * 35 + 4, p.Y * 35 + 4)
        '换算成像素坐标
        If Box(p.X, p.Y) <> Chess.none Then
            Return
        End If
        ' Label2.Text = p2.X.ToString() & "|" & p2.Y.ToString()
        ImageList1.Draw(g, p2, CInt(mplayer))
        PictureBox1 = New PictureBox()
        PictureBox1.Refresh()  '刷新
        Box(p.X, p.Y) = mplayer
        Label2.Text = Box(p.X, p.Y).ToString()
        Dim str_send As String = ("move|" + Label1.Text & "|") + Label2.Text
        can_go = False
        send(str_send)
        If win_lose() = True Then  '判断输赢否
            str_send = "over|" & mplayer.ToString()
            winner = mplayer
            Label6.Text = mplayer.ToString() & "赢了此局！"
            BtnReStart.Enabled = True
            send(str_send)
        End If
    End Sub
    '从图片框位图中获取graphics对象
    Public Function GetGraphicsObject(ByRef pic As PictureBox) As Graphics
        Dim bmp As New Bitmap("棋盘.jpg")
        pic.Image = bmp
        g = Graphics.FromImage(bmp)
        Return g
    End Function
    Private Sub Form1_FormClosed(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed
        If th_flag = True Then
            If th.IsAlive Then
                th.Abort()
            End If
        End If
    End Sub
    'Protected Overrides Sub Dispose(disposing As Boolean)
    'Try
    '        ReadFlag = False
    'f Not IsDBNull(udpclient) Then udpclient.Close()
    'If Not IsDBNull(th) Then th.Abort()
    '       th = Nothing
    'Catch
    'End Try
    'If disposing AndAlso components IsNot Nothing Then
    '       components.Dispose()
    'End If
    'MyBase.Dispose(disposing)
    'End Sub
    Private Sub 退出ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles 退出ToolStripMenuItem.Click
        End '就是退出程序
    End Sub
    '底下都是用来截屏的
    <DllImport("user32.dll")>
    Private Shared Function GetDesktopWindow() As IntPtr
    End Function

    <DllImport("user32.dll")>
    Private Shared Function GetWindowRect(hWnd As IntPtr, ByRef rect As RECT) As IntPtr
    End Function

    <StructLayout(LayoutKind.Sequential)>
    Private Structure RECT
        Public Left As Integer
        Public Top As Integer
        Public Right As Integer
        Public Bottom As Integer
    End Structure
    Private Sub SaveScreenshot(filename As String)
        Dim screenRect As New RECT()
        Dim hWnd As IntPtr = GetDesktopWindow()
        GetWindowRect(hWnd, screenRect)

        Dim screenWidth As Integer = screenRect.Right - screenRect.Left
        Dim screenHeight As Integer = screenRect.Bottom - screenRect.Top

        Using bmp As New Bitmap(screenWidth, screenHeight)
            Using g As Graphics = Graphics.FromImage(bmp)
                g.CopyFromScreen(New Point(0, 0), Point.Empty, New Size(screenWidth, screenHeight))
            End Using
            bmp.Save(filename, ImageFormat.Png)
        End Using
    End Sub
    Private Sub 截图ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles 截图ToolStripMenuItem.Click
        SaveScreenshot("C:\Users\Administrator\Desktop\screenshot.png")
    End Sub
    Private Sub 游戏作者ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles 游戏作者ToolStripMenuItem.Click
        Form2.ShowDialog()  '传form2上来(@_@)!（颜文字证实是我自己打的
    End Sub

    Private Sub BtnStopGame_Click(sender As Object, e As EventArgs) Handles BtnStopGame.Click
        Application.Exit()
    End Sub

    Private Sub 计算机ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles 计算机ToolStripMenuItem.Click
        calc.Show()
    End Sub

    Private Sub 贪吃蛇ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles 贪吃蛇ToolStripMenuItem.Click
        snake.Show()
    End Sub

    Private Sub 聊天ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles 聊天ToolStripMenuItem.Click
        chat.Show()
    End Sub
End Class
